package cx3k.dataaccess.test;

import java.io.PrintStream;
import java.util.ArrayList;
//import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.hibernate.Session;
import org.hibernate.Transaction;

import cx3k.scheduler.objects.GroupedCourse;
import cx3k.scheduler.objects.Major;
import cx3k.scheduler.objects.Minor;
import cx3k.scheduler.objects.RequirementGrouping;

public class ManageGroupings {

	private static enum MenuOption {
		ADD_MAJOR		(1, "Add Major"),
		REMOVE_MAJOR	(2, "Remove Major"),
		ADD_MINOR		(3, "Add Minor"),
		REMOVE_MINOR	(4, "Remove Minor"),
		ADD_GROUPING	(5, "Add Grouping"),
		REMOVE_GROUPING	(6, "Remove Grouping"),
		QUIT			(7, "Quit");
		
		private int code;
		private String value;
		
		private MenuOption(int code, String value){
			this.code = code;
			this.value = value;
		}
		
		public int getCode(){
			return code;
		}
		
		public String getValue(){
			return value;
		}
		
		public String toString(){
			return getCode() + ".\t" + getValue();
		}
	}
	

	@SuppressWarnings("unchecked")
	private static void addGrouping(){
		
		List<Major> selectedMajors = new ArrayList<Major>(2);
		List<Minor> selectedMinors = new ArrayList<Minor>(1);
		
		Session session = getSession();
		Transaction tx;
		
		// get majors
		tx = session.beginTransaction();
		
		List<Major> majors = (List<Major>) session.createQuery("from Major as major").list();
		
		tx.commit();
		
		Util.printHeader("Majors");
		
		// display majors
		do{
			int count = 1;
			for(Major major : majors){
				System.out.println(count++ + ".\t" + major.getProgram() + " : " + major.getDescription());
			}
			
			Major selected = majors.get(Util.getValidInt(1, majors.size(), "Major") - 1);
			if(selected != null){
				selectedMajors.add(selected);
				majors.remove(selected);
			}
			
		} while(selectedMajors.size() < 2 && Util.getYesNo("Add another major?"));
		
		Util.printHeader("Minors");
		
		if(selectedMajors.size() < 2 && Util.getYesNo("Add minor?")){
			tx = session.beginTransaction();
			
			List<Minor> minors = (List<Minor>) session.createQuery("from Minor as minor").list();
			
			tx.commit();
			
			do{
				int count = 1;
				for(Minor minor : minors){
					System.out.println(count++ + ".\t" + minor.getProgram() + " : " + minor.getDescription());
				}
				
				Minor selected = minors.get(Util.getValidInt(1, minors.size(), "Minor") - 1);
				if(selected != null){
					selectedMinors.add(selected);
					minors.remove(selected);
				}
			} while(selectedMinors.size() < 1 && Util.getYesNo("Add another minor?"));
		}
		
		String query = "from RequirementGrouping as grouping where grouping.major.majorId = " + selectedMajors.get(0).getMajorId();
		if(selectedMinors.size() >= 1){
			query += " and grouping.minor.minorId = " + selectedMinors.get(0).getMinorId();
		}
		
		tx = session.beginTransaction();
		
//		List<RequirementGrouping> requirementGroupings = (List<RequirementGrouping>) session.createQuery(query).list();
		
		tx.commit();
		
		RequirementGrouping grouping = new RequirementGrouping();
		
		grouping.setMajor(selectedMajors.get(0));
		
		if(!selectedMinors.isEmpty()){
			grouping.setMinor(selectedMinors.get(0));
		}
		
		grouping.setCreditsRequired(Util.getValidInt(0, "How many credits are required?"));
		
		StringBuffer prereqs = new StringBuffer();
		Set<String> preReqSet = new TreeSet<String>();
		
		do{
			GroupedCourse course = new GroupedCourse();
			
			course.setDegreeProgram(Util.getInput("Degree program"));
			course.setCourseNum(Util.getInput("Course number"));
			
			tx = session.beginTransaction();
			
			/*if(session.createQuery("from Course as course where course.courseNum = '" + 
					course.getCourseNum() + "' and course.degreeProgram = '" + 
					course.getDegreeProgram() + "'").list().isEmpty()){
				System.err.println("Invalid course: course " + course.getDegreeProgram() + " " + course.getCourseNum() + " does not exist in database.");
			} else {
			*/
				course.setCredits(Util.getInput("Number of credits"));
				
				
				if(Util.getYesNo("Does course have pre-requisites?")){
					do{
						String prereqDegreeProgram = Util.getInput("Pre-requisite degree program");
						String prereqCourseNumber = Util.getInput("Pre-requisite course number");
						
						/*if(session.createQuery("from Course as course where course.courseNum = '" + 
								prereqCourseNumber + "' and course.degreeProgram = '" + 
								prereqDegreeProgram + "'").list().isEmpty()){
							System.err.println("Invalid pre-requisite: course " + prereqDegreeProgram + " " + prereqCourseNumber + " does not exist in database."); 
						} else {
						*/	
//							prereqs.append(prereqDegreeProgram + prereqCourseNumber + ",");
							if(preReqSet.add(prereqDegreeProgram + prereqCourseNumber)){
								prereqs.append(prereqDegreeProgram + prereqCourseNumber + ",");
							}
//						}
					} while(Util.getYesNo("Add another pre-requisite?"));
					
//					course.setPreReqs(prereqs.toString());
				}
				
				
				
				course.setRequirementGrouping(grouping);
				grouping.getGroupedCourses().add(course);
				
				session.saveOrUpdate(grouping);
				
				System.out.println("Saved grouping [ID = " + grouping.getRequirementGroupingId() + "]");
//			}
			
			tx.commit();
		} while(Util.getYesNo("Add another course?"));
		
		for(GroupedCourse course : grouping.getGroupedCourses()){
			course.setPreReqs(prereqs.toString());
			
			tx = session.beginTransaction();
			session.saveOrUpdate(course);
			tx.commit();
		}
		
		session.close();
		
	}
	
	@SuppressWarnings("unchecked")
	private static void removeMinor(){
		Session session = getSession();
		Transaction tx = session.beginTransaction();
		
		List<Minor> minors = (List<Minor>) session.createQuery("from Minor as minor").list();
		
		tx.commit();
		
		Util.printHeader("Current Minors");
		int count = 1;
		
		for(Minor minor : minors){
			System.out.println(count++ + ".  " + minor.getProgram() + " [" + minor.getMinorId() + "]");
		}
		
		Minor deleteThis = minors.get(Util.getValidInt(1, minors.size(), "Minor") - 1);
		
		if(Util.getYesNo("Are you sure?")){
			tx = session.beginTransaction();
			
			session.delete(deleteThis);
			
			tx.commit();
		}
		
		session.close();
	}
	
	@SuppressWarnings("unchecked")
	private static void addMinor(){
		Session session = getSession();
		Transaction tx = session.beginTransaction();
		
		List<Minor> minors = (List<Minor>) session.createQuery("from Minor as minor").list();
		
		tx.commit();
		
		Util.printHeader("Current Majors");
		
		for(Minor minor : minors){
			System.out.println("\t-  " + minor.getProgram() + " [" + minor.getMinorId() + "]");
		}
		
		if(Util.getYesNo("Add new minor?")){
			Minor newMinor = new Minor();
			
			newMinor.setProgram(Util.getInput("Minor program"));
			newMinor.setDescription(Util.getInput("Description"));
			
			tx = session.beginTransaction();
			
			session.save(newMinor);
			
			tx.commit();
		}
		
		session.close();
	}
	
	@SuppressWarnings("unchecked")
	private static void removeMajor(){
		
		Session session = getSession();
		Transaction tx = session.beginTransaction();
		
		List<Major> majors = (List<Major>) session.createQuery("from Major as major").list();
		
		tx.commit();
		
		Util.printHeader("Current Majors");
		int count = 1;
		
		for(Major major : majors){
			System.out.println(count++ + ".  " + major.getProgram() + " [" + major.getMajorId() + "]");
		}
		
		Major deleteThis = majors.get(Util.getValidInt(1, majors.size(), "Major")  - 1);
		
		if(Util.getYesNo("Are you sure?")){
			tx = session.beginTransaction();
			
			session.delete(deleteThis);
			
			tx.commit();
		}
		
		session.close();
	}
	
	@SuppressWarnings("unchecked")
	private static void addMajor(){
		
		Session session = getSession();
		Transaction tx = session.beginTransaction();
		
		List<Major> majors = (List<Major>) session.createQuery("from Major as major").list();
		
		tx.commit();
		
		Util.printHeader("Current Majors");
		
		for(Major major : majors){
			System.out.println("\t-  " + major.getProgram() + " [" + major.getMajorId() + "]");
		}
		
		if(Util.getYesNo("Add new major?")){
			Major newMajor = new Major();
			
			newMajor.setProgram(Util.getInput("Major program"));
			newMajor.setDescription(Util.getInput("Description"));
			
			tx = session.beginTransaction();
			
			session.save(newMajor);
			
			tx.commit();
		}
		
		session.close();
		
		
	}
	
	private static Session getSession(){
		return HibernateUtil.getSessionFactory().openSession();
	}
	
	public static void main(String[] args){
				
		
		Util.printHeader("Manage Class Groupings");
		System.out.println("Manage groupings for the scheduler.");
		
		try {
			System.setOut(new PrintStream("C:\\Users\\Chris\\workspace\\cx3kScheduler\\src\\results.txt"));
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		MenuOption input = menu();
		
		while(!input.equals(MenuOption.QUIT)){
			
			switch(input){
				case ADD_MAJOR:
					addMajor();
					break;
				case REMOVE_MAJOR:
					removeMajor();
					break;
				case ADD_MINOR:
					addMinor();
					break;
				case REMOVE_MINOR:
					removeMinor();
					break;
				case ADD_GROUPING:
					addGrouping();
					break;
				case REMOVE_GROUPING:
					
					break;
			}
			
			input = menu();
		}
		
		System.err.println("Done");
		
	}
	
	private static MenuOption menu(){
		printMenu();
		return getMenuOption();
	}
	
	private static MenuOption getMenuOption(){
		return MenuOption.values()[Util.getValidInt(1, MenuOption.values().length, "Selection") - 1];
	}
	
	private static void printMenu(){
		Util.printHeader("Main Menu");
		
		for(MenuOption option : MenuOption.values()){
			System.out.println(option);
		}
	}
	
	
}
